package com.vpclub.proxy;

import com.vpclub.inter.Calculator;
import com.vpclub.utils.LogUtils;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

/**
 * @author : leimingchao
 * @version V1.0
 * @Project: springdemo
 * @Package com.vpclub.proxy
 * @Description: 帮 Calculator生成代理对象
 *
 * Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)
 *
 * @date Date : 2021年06月03日 23:01
 */
public class CalculatorProxy {

    /**
     *为传入的参数对象创建一个动态代理对象
     * @param calculator
     *
     * Calculator calculator：被代理对象；（宝宝）
     * 返回的：宋喆
     * @return
     */
    public static Calculator getProxy(final Calculator calculator) {

        //方法执行器，帮我们目标对象执行目标方法
        InvocationHandler h = new InvocationHandler() {
            /**
             *
             * @param proxy:代理对象，给jdk使用，任何时候都不要动这个对象
             * @param method:当前将要执行的目标对象的方法
             * @param args:这个方法调用的时候外界传入的参数值
             * @return
             * @throws Throwable
             */
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                //System.out.println("这是动态代理将要帮你执行的方法。。。。。");
                // System.out.println(proxy.getClass().getName());
                //利用反射执行目标方法
                //目标方法执行后的返回值
                Object result = null;
                try {
                    LogUtils.logStart(method,args);
                    result = method.invoke(calculator, args);
                    LogUtils.logReturn(method,result);
                } catch (Exception e) {
                    LogUtils.logException(method,e);
                } finally {
                    LogUtils.logEnd(method);
                }
                //返回值必须返回出去外界才能拿到真正执行后的返回值
                return result;
            }
        };
        ClassLoader loader = calculator.getClass().getClassLoader();
        Class<?>[] interfaces = calculator.getClass().getInterfaces();

        //proxy为目标对象创建代理对象
        Object proxy = Proxy.newProxyInstance(loader, interfaces, h);
        return (Calculator) proxy;
    }
}
